<?php

namespace App\Http\Controllers\Logic;

use App\Exceptions\BusinessException;
use App\Helpers\ProjectHelper;
use App\Http\Controllers\Constant\Constant;
use App\Http\Controllers\Controller;
use App\Model\OACity;
use App\Model\OAFiles;
use App\Model\OAFinance;
use App\Model\OAFinanceClv;
use App\Model\OAPositionMapping;
use App\Model\OAProjectLx;
use App\Model\OAProjectYs;
use App\Model\OAProjectYsDetail;
use App\Model\OAShenPiLog;
use App\Model\OAStaff;
use App\Model\OATicket;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;

class FinanceLogic extends Controller
{
    //计算价格
    public function getClvFee($params)
    {
        $fee = OACity::query()->where('level', Arr::get($params,'city_level',1))->value('money');
        $people = count($params['staff_list']);
        $days = $this->calculateDay($params['date'][0], $params['date'][1]);
        if ($days > 30) throw new \Exception('出差天数不可大于30天,请重新选择');
        $ren = intval($people / 2);
        $cost = ($people * $fee - 100 * $ren) * $days;
        return ['cost' => bcadd((string) $cost,'0.00',2), 'day' => $days];
    }

    public function calculateDay($day1, $day2)
    {
        return Carbon::parse($day1)->diffInDays(Carbon::parse($day2));
    }

    //获取可申请项目
    public function getApplyProject($params)
    {
        $type = $params['type'];

        $uid = $params['uid'];

        $roleid = $params['roleid'];

        $query = OAProjectYs::query();

        $query->where('a.create_role', $roleid);//创建者角色

        $query->where('a.uid', $uid);//创建者

        switch ($type) {
            case 3:
                //todo
                $query->where('a.type', 2);
                break;
            case 5:
                $query->where('b.status', 2);//立项走完就可以申请
                break;
            default:
                $query->where('a.status', 2);//必须预算走完
        }

        $list = $query->from('project_ys AS a')
            ->leftJoin('project_lx AS b', 'b.id', '=', 'a.xmid')
            ->select(['b.id', 'b.name'])
            ->distinct(true)
            ->orderByDesc("b.created_at")
            ->get()
            ->toArray();

        return $list;

    }

    //获取财务模块,项目基本信息
    public function getProjectBase($params)
    {
        $info = $this->getBaseInfo($params);
        $payList = [Constant::PAY_TYPE_CLV, Constant::PAY_TYPE_CM,
            Constant::PAY_TYPE_JK, Constant::PAY_TYPE_YJ, Constant::PAY_TYPE_LK];
        if (in_array($params['type'],$payList )) {
            $limit = OAProjectYsDetail::query()
                ->where('xmid', $info->id)
                ->where('paytype', $params['type'])
                ->first(['money', 'jsmoney']);

            if (is_null($limit)) $info->limit = 0;
            else $info->limit = $limit->jsmoney > 0 ? $limit->jsmoney : $limit->money;
        } elseif ($params['type'] == Constant::PAY_TYPE_FP) {
            $info->limit = $info->offer;
        } else {
            //0:结算时的火车票
            $limit = OAProjectYsDetail::query()
                ->where('xmid', $info->id)
                ->whereIn('paytype', [4,0])
                ->select(['id', 'title', 'money', 'jsmoney'])
                ->get()
                ->toArray();
            if (empty($limit)) {
                $info->fKuanList = [];
            } else {
                foreach ($limit as &$fk) {
                    $fk['money'] = $fk['jsmoney'] > 0 ? $fk['jsmoney'] : $fk['money'];
                    unset($fk['jsmoney']);
                }
                $info->limit = 0;
                $info->fKuanList = $limit;
            }

        }
        $ys = OAProjectYs::query()
            ->where('xmid', $params['id'])
            ->select(['type', 'cost', 'offer'])
            ->get()
            ->toArray();
        $ys = array_column($ys, null, 'type');
        $info->offer_ys = $info->cost_ys = $info->offer_js = $info->cost_js = '0.00';
        if (array_key_exists(OAProjectYs::PROJECT_YS, $ys)) {
            $info->offer_ys = $ys[OAProjectYs::PROJECT_YS]['offer'] ?? '0.00';
            $info->cost_ys = $ys[OAProjectYs::PROJECT_YS]['cost'] ?? '0.00';
        }
        if (array_key_exists(OAProjectYs::PROJECT_JS, $ys)) {
            $info->offer_js = $ys[OAProjectYs::PROJECT_JS]['offer'] ?? '0.00';
            $info->cost_js = $ys[OAProjectYs::PROJECT_JS]['offer'] ?? '0.00';
        }
        return $info;
    }

    //添加财务申请
    public function addFinanceData(Request $request)
    {
        try {
            DB::beginTransaction();
            $params = $request->all();
            $type = $request->input('type');
            $lx = OAProjectLx::query()->find(Arr::get($params,'xmid'));
            if(is_null($lx)) throw new \Exception("立项不存在");
            if(is_array(Arr::get($params,'finance.name',''))){
                $fukuanArr = Arr::get($params,'finance.name');
                $params['finance']['title'] = Arr::get($fukuanArr,'title');
            }else{
                $params['finance']['title'] = Arr::get($params,'finance.name','');
            }
            if(!Arr::get($params,'finance.title','')) throw new \Exception(sprintf("%s名称不能为空",cwName($type)));
            $inputMoney = Arr::get($params,'finance.money','0.00');
            $ysid = $request->input('ysid',0);
            $this->vaildFinanceLimit($inputMoney,$ysid);//是否超出限额
            $this->vaildRepeatApply($params);
            $work_list = config('oa.finance');
            $work_id = $cwData['work_id'] = $work_list[$type]['work_id'];
            $is_save = $cwData['is_save'] = $params['is_save'];
            $cwData['xmid'] = $params['xmid'];
            $finceData = $params['finance'];
            $cwData['title'] = $finceData['title'];
            $cwData['money'] = resetMoney($finceData['money']);
            if($cwData['money'] < 1) throw new \Exception("申请金额不能为空");
            $cwData['uid'] = $params['uid'];
            $cwData['create_role'] = $params['roleid'];
            $roleid = $params['roleid'];
            $node_id = $this->getCurrentNode($work_id, $roleid);
            $cwData['created_at'] = $cwData['updated_at'] = date('Y-m-d H:i:s');
            $cwData['desc'] = Arr::get($finceData,'desc');
            $cwData['ysid'] = Arr::get($params,'ysid');
            //获取财务流水号
            $cwData['batch_id'] = $this->generateFinanceBatchNum($params['batch_id']);
            $status = 0;
            if (!$is_save) {
                if(empty(Arr::get($cwData,'desc',''))) throw new \Exception('备注不能为空');
                $nextApprove = $this->getNextApprover($node_id, $work_id, 1);
                $roleid = $nextApprove['roleid'];
                $node_id = $nextApprove['node_id'];
                $status = Arr::get($nextApprove,'status');
            }
            $cwData['roleid'] = $roleid;
            $cwData['node_id'] = $node_id;
            $cwData['paytype'] = $params['type'];
            $cwData['status'] = $status;
            if (isset($finceData['ticket_id']) && !empty($finceData['ticket_id'])) $cwData['ticket_id'] = $finceData['ticket_id'];
            if (isset($finceData['ticket_category']) && !empty($finceData['ticket_category'])) $cwData['ticket_category'] = $finceData['ticket_category'];
            if (isset($finceData['ticket_type']) && !empty($finceData['ticket_type'])) $cwData['ticket_type'] = $finceData['ticket_type'];
            //存差旅数据
            $clv_list = Arr::get($finceData,'clv_list',[]);
            $clvData = [];
            if ($type == Constant::PAY_TYPE_CLV && $clv_list) {
                $this->checkClvList($clv_list);//检查差旅
                foreach ($clv_list as $clv) {
                    $xmid = Arr::get($params,'xmid');
                    $clvName = Arr::get($clv,'name');
                    $exists = OAFinanceClv::query()->where('xmid',$xmid)->where('name',$clvName)->exists();
                    if($exists) throw new \Exception(sprintf("差旅名称%s重复",$clvName));
                    $clvData[] = [
                        'name' => $clv['name'],
                        'cost' => $clv['cost'],
                        'city' => $clv['city'],
                        'city_level' => $clv['city_level'],
                        'start' => Arr::first($clv['date']),
                        'end' => Arr::last($clv['date']),
                        'staff_list' => $clv['staff_list'],
                        'day' => $clv['day'],
                        'sex'=>Arr::get($clv,'sex',1),
                        'xmid'=>$xmid,
                    ];
                }
                $cwData['title'] = Arr::get(Arr::first($clvData),'name','差旅费');
            }
            //dd($cwData);
            $finance_id = Arr::get($params,'cwid',0);
            if ($finance_id) {
                $finance = OAFinance::query()->find($finance_id);
                Arr::forget($cwData,'ysid');
                $finance->fill($cwData)->save();
            } else {
                $processLink = ProjectHelper::getRolesAndUidsByWorkIdAndGsId($work_id,$lx->gsid);
                $cwData['deptid'] = $lx->deptid;
                $cwData = array_merge($processLink,$cwData);
                $finance = OAFinance::query()->create($cwData);
                $finance_id = $finance->id;
            }
            if (!empty($params['file_list'])) $this->saveFileList($finance_id, $params['file_list'], FILE_FINANCE,$work_id);

            if($clvData){
                $finance->clvs()->delete();
                $finance->clvs()->createMany($clvData);
            }
            //保存日志记录
            if(!$is_save){
                $cw_title = Arr::get($params,'finance.title','');
                OAShenPiLog::createShenPiLogs($work_id,$finance_id,"提交财务[{$cw_title}]",OAShenPiLog::SHENPI_STATUS_PASS);
            }

            DB::commit();
            return $finance_id;
        } catch (\Exception $e) {
            DB::rollBack();
            //dd($e);
            throw new \Exception($e->getMessage());
        }
    }

    //获取财务列表
    public function getList($params)
    {
        //dd($params);
        $roleid = roleid();
        $isAdmin = $this->isAdmin($roleid);
        DB::enableQueryLog();
        $list = OAFinance::query()
            ->roles()
            ->status(Arr::get($params,'status'))
            //流水号
            ->when(isset($params['batch_id']) && !empty($params['batch_id']),function ($q) use ($params){
                return $q->where('batch_id', $params['batch_id']);
            })
            //财务名称
            ->when(isset($params['title']) && !empty($params['title']),function ($q) use ($params){
                return $q->where('title', 'like', '%' . $params['title'] . '%');
            })
            //财务类型
            ->when(isset($params['paytype']) && !empty($params['paytype']),function ($q) use ($params){
                return $q->where('paytype', $params['paytype']);
            })
             //创建时间
            ->when(isset($params['date']) && !empty($params['date']),function ($q) use ($params){
                    return $q->whereBetween('created_at', $params['date']);
             })
            //创建者
            ->when(isset($params['created_user']) && !empty($params['created_user']),function ($q) use ($params){
                return $q->whereIn('uid', $params['created_user']);
            })
        ->orderBy('updated_at', 'desc')
        ->latest("created_at")

        ->paginate($params['page_size'], [
         'batch_id', 'title', 'uid', 'money', 'id', 'updated_at', 'paytype','xmid'
        ])
        ->toArray();
        // projectName
       if($data = Arr::get($list,'data',[])){
           $xmids = array_column($data,'xmid');
           $xmids = array_filter(array_unique($xmids));
           $lxList = OAProjectLx::query()->whereIn('id',$xmids)->select(['id','name'])->get()->toArray();
           $lxList = array_column($lxList,"name","id");
           foreach ($data as &$item){
               $item['projectName'] = Arr::get($lxList,$item['xmid']);
           }
           $list['data'] = $data;
       }
        return $list;
    }

    //获取财务详情
    public function getFinanceDetail($params)
    {
        $finance = OAFinance::query()->where('id', $params['id'])->first();
        $input['type'] = $finance->paytype;
        $input['id'] = $finance->xmid;
        $finance->baseInfo = $this->getProjectBase($input);
        $finance->baseInfo->batch_id = $finance->batch_id;
        $finance->summaryData = $finance->summary;
        //差旅
        if ($finance->paytype == Constant::PAY_TYPE_CLV) {
            $clv_list = OAFinanceClv::query()->where('pid', $params['id'])->select()->get()->toArray();
            $finance->clv_list = $clv_list;
        }

        //发票
        if ($finance->paytype == Constant::PAY_TYPE_FP) {
            $finance->ticketList = $this->getTicketList(['page' => 1, 'page_size' => 9999, 'status' => 1]);
            $finance->ticketInfo = $this->getTicketInfo(['id' => $finance->ticket_id]);
            $ticket = config('oa.ticket');
            $finance->ticketCategory = $ticket['category'];
            $finance->ticketType = $ticket['type'];
        }

        try {
            $finance->history = (new ApproveHistory())->getApproveHistory($finance);
            $finance->file_list = $this->getFileList($finance->id, FILE_FINANCE);
            $finance->hzd_list = $this->getFileList($finance->id,FILE_HZD,$finance->work_id);//回执单
            $finance->spForm = OAShenPiLog::getTempSpFormData($finance->work_id,$finance->id);
        } catch (\Exception $e) {
            throw new \Exception($e->getMessage());
        }

        return $finance;
    }

    //编辑财务
    public function editFinance(Request $request,OAFinance $info)
    {
          $params = $request->all();
        try {
            DB::beginTransaction();
            $finance = $params['finance'];
            $type = $finance['paytype'];
            $isSave = $params['is_save'];
            $finance['finance'] = $params['finance'];
            $financeConfig = config('oa.finance');
            $config = Arr::get($financeConfig,$type,[]);
            $paytypeName = Arr::get($config,'name','财务');
            $desc = Arr::get($finance,'desc','');
            if(!$isSave && empty($desc)) throw new \Exception("备注不能为空");
            $this->vaildRepeatApply($params);
            //检查是否超出限额
            $this->vaildFinanceLimit(Arr::get($finance,'money'),Arr::get($finance,'ysid'),Arr::get($params,'id'));
            $log = $this->checkDifferentData($finance, 'cw');
            if ($type == Constant::PAY_TYPE_CLV) $this->getClvlog($finance, true);
            if ($type == Constant::PAY_TYPE_FP) $this->getTicketLog($finance, true);
            if ($log) {
                OAShenPiLog::createShenPiLogs($info->work_id,$info->id,$log,OAShenPiLog::SHENPI_STATUS_LOG);
            }else{
                if(isPM() && !$isSave) {
                    $isExists = OAShenPiLog::checkShenLogExists($info->work_id,$info->id,OAShenPiLog::SHENPI_STATUS_PASS);
                    if(!$isExists)OAShenPiLog::createShenPiLogs($info->work_id,$info->id,'创建'.Arr::get($finance,'cw_title'),OAShenPiLog::SHENPI_STATUS_PASS);
                }
            }
            //保存文件
            $this->saveFileList($info->id,Arr::get($finance,'file_list'),FILE_FINANCE,$info->work_id);

            //提交时改变流程
            if(!$isSave && $request->roleid == $info->create_role){
                if($type == Constant::PAY_TYPE_YJ){
                    $nextApprover = $this->getYaJinReturn($params, $info);
                    $info->work_id = $nextApprover['work_id'];
                    $info->node_id = $nextApprover['node_id'];
                    $info->roleid = $nextApprover['roleid'];
                    $info->status = $nextApprover['status'];
                }else{
                    $nextApprover = $this->getNextApprover($info->node_id, $info->work_id, 1,$info->create_role);
                    $info->node_id = $nextApprover['node_id'];
                    $info->roleid = $nextApprover['roleid'];
                    $info->status = $nextApprover['status'];
                }

            }

            $info->title = Arr::get($finance,'title');
            $info->money = resetMoney($finance['money']);
            $info->desc = $desc;
            $info->is_save = $request->input('is_save');
            $info->save();

            //审批附件+备注
            $spForm = Arr::get($params,'spForm',[]);
            if($spForm){
                $note = Arr::get($spForm,'note','无');
                $spLog = OAShenPiLog::createShenPiLogs($info->work_id,$info->id,$note,OAShenPiLog::SHENPI_STATUS_NOTHING);
                $file_list = Arr::get($spForm,'fileList',[]);
                if($file_list) $this->saveFileList($spLog->id,$file_list,OAFiles::FILE_TYPE_TEMP,$info->work_id);
            }

            // 回执单
            if($hzdList = Arr::get($params,'finance.hzd_list',[])){
                $this->saveFileList($info->id,$hzdList,FILE_HZD,$info->work_id);
            }

            DB::commit();
            return true;

        } catch (\Exception $e) {
            //dump($e);
            DB::rollBack();
            throw new \Exception($e->getMessage());
        }
    }

    //获取发票列表
    public function getTicketList($input)
    {
        $status_list = ['禁用', '启用'];
        $query = OATicket::query();
        $page = $input['page'] ?? 1;
        $page_size = $input['page_size'] ?? 10;
        //$status = $input['status'] ?? 1;
        if (!isset($input['is_list']) && empty($input['is_list'])) return $query->where('status', 1)->get(['id', 'name'])->toArray();
        //账号
        if (isset($input['account']) && !empty($input['account'])) $query->where('account', 'like', "%{$input['account']}%");
        //开户行
        if (isset($input['bank']) && !empty($input['bank'])) $query->where('bank', 'like', "%{$input['bank']}%");
        //简称
        if (isset($input['short_name']) && !empty($input['short_name'])) $query->where('short_name', 'like', "%{$input['short_name']}%");
        //状态
        if(isset($input['status']))$query->where('status', $input['status']);
        $list = $query->orderBy('updated_at', 'DESC')->paginate($page_size, ['*']);
        $list = $list->toArray();
        if (!$list['data']) return $list;
        $common = new CommonLogic();
        $userAll = $common->getAllRoleAndUser('user_all');
        foreach ($list['data'] as &$datum) {
            //$datum['status'] = $status_list[$datum['status']];
            $datum['create_user'] = $userAll[$datum['uid']] ?? '-';
        }
        return $list;
    }

    //获取发票详情
    public function getTicketInfo($params)
    {
        return OATicket::query()->where('id', $params['id'])->first();
    }

    //编辑发票
    public function addTicket($input)
    {
        try {
            DB::beginTransaction();
            $ticket = OATicket::query()->where('id', $input['id'])->first();
            if(isset($input['is_company'])) unset($input['is_company']);
            if (!is_null($ticket)) {
                $ticket->name = $input['name'];
                $ticket->account = $input['account'];
                $ticket->short_name = $input['short_name'];
                $ticket->address = $input['address'];
                $ticket->bank = $input['bank'];
                $ticket->batch_id = $input['batch_id'];
                $ticket->bank_number = $input['bank_number'];
                $ticket->mobile = $input['mobile'];
                $ticket->status = $input['status'];
                $ticket->uid = $input['uid'];
                $ticket->save();
            } else {
                $input['created_at'] = $input['updated_at'] = date("Y-m-d H:i:s");
                unset($input['id'],$input['roleid'],$input['deptid']);
                OATicket::query()->insertGetId($input);
            }
            DB::commit();
            return true;
        } catch (\Exception $e) {
            DB::rollBack();
            throw new \Exception($e->getMessage());
        }
    }

    //获取差旅
    public function getClvData($params)
    {
        $data = OAFinanceClv::query()->where('pid', $params['id'])->select()->get()->toArray();
        if (empty($data)) return [];
        return $data;
    }

    //获取财务申请记录
    public function getApplyLog($params)
    {
        $list = OAFinance::query()
        ->where('xmid', $params['xmid'])
        ->where('paytype', $params['type'])
        ->when($ysid = Arr::get($params,'ysid',0),function ($q) use ($ysid){
            return  $q->where('ysid', $ysid);
        })
        ->select(['title', 'money', 'created_at', 'status','ysid'])
        ->get()
        ->toArray();

        $dai = $yi = [];
        $daiSum = $yiSum = 0;
        if($list) {
            foreach ($list as $item) {
                $log = [
                    'title' => $item['title'],
                    'money' => number_format($item['money'], 2),
                    'date' => $item['created_at']
                ];

                if ($item['status'] == 2) {
                    $yiSum += $item['money'];
                    $yi[] = $log;
                } else {
                    $daiSum += $item['money'];
                    $dai[] = $log;
                }
            }
        }
        //获取限额
        $ys = OAProjectYsDetail::query()
                      ->where('xmid',Arr::get($params,'xmid'))
                      ->where('paytype',Arr::get($params,'type'))
                        ->when($ysid = Arr::get($params,'ysid',0),function ($q) use ($ysid){
                        return  $q->where('id', $ysid);
                        })
            ->first();
        $limitMoney = optional($ys)->money ?? '0.00';
        $ysid = optional($ys)->id ?? 0;
        $ableApply = $limitMoney - $yiSum - $daiSum;
        return [
            'dai' => $dai,
            'yi' =>  $yi,'0.00',
            'yiSum' => bcadd((string)$yiSum,'0.00',2),
            'daiSum' => bcadd((string)$daiSum,'0.00',2),
            'ableSum' => bcadd((string)$ableApply,'0.00',2),
            'limit'=>$limitMoney,
            'applyedSum'=> bcadd($yiSum,$daiSum,2),
            'limit_title'=>Constant::getFinanceCategory(Arr::get($params,'type')),
            'ysid'=>$ysid,
        ];
    }
}
